home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / misc / volume23 / ison / part01 next >
Encoding:
Text File  |  1991-10-21  |  13.3 KB  |  400 lines

  1. Newsgroups: comp.sources.misc
  2. From: mgleason@cse.unl.edu (Mike Gleason)
  3. Subject:  v23i103:  ison - be informed when a user logs on, Part01/01
  4. Message-ID: <1991Oct22.033547.2041@sparky.imd.sterling.com>
  5. X-Md4-Signature: 4e5948f888ff87db821cafeb26e8e06b
  6. Date: Tue, 22 Oct 1991 03:35:47 GMT
  7. Approved: kent@sparky.imd.sterling.com
  8.  
  9. Submitted-by: mgleason@cse.unl.edu (Mike Gleason)
  10. Posting-number: Volume 23, Issue 103
  11. Archive-name: ison/part01
  12. Environment: UNIX
  13.  
  14. IsOn's purpose is to let you know when someone logs on.  You could always sit
  15. there at your terminal typing 'finger' or 'who' every 5 minutes, but that's
  16. boring and unproductive.  IsOn makes this easy.  If you wanted to know the
  17. instant I logged on, all it would take is a simple:
  18.  
  19.    ison mgleason@cse.unl.edu &
  20.  
  21. When I do log on, ison would respond:
  22.  
  23.    ** mgleason logged in since Wed Oct 16 02:19:33 1991
  24.  
  25. IsOn lowers it's priority automatically, so it takes very little CPU, and
  26. spares you the trouble of remembering to use 'nice.'  For remote addresses
  27. (those in dude@machine.domain format) the 'finger' utility is used, or for
  28. a user on the same machine that you are on, IsOn will simply walk the 'utmp'
  29. file.
  30.  
  31. Enjoy!
  32.  --mike gleason = mgleason@cse.unl.edu
  33.  
  34. #! /bin/sh
  35. # This is a shell archive.  Remove anything before this line, then unpack
  36. # it by saving it into a file and typing "sh file".  To overwrite existing
  37. # files, type "sh file -c".  You can also feed this as standard input via
  38. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  39. # will see the following message at the end:
  40. #        "End of shell archive."
  41. # Contents:  ison.c ison.readme
  42. # Wrapped by mgleason@cse on Wed Oct 16 06:00:19 1991
  43. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  44. if test -f 'ison.c' -a "${1}" != "-c" ; then 
  45.   echo shar: Will not clobber existing file \"'ison.c'\"
  46. else
  47. echo shar: Extracting \"'ison.c'\" \(9646 characters\)
  48. sed "s/^X//" >'ison.c' <<'END_OF_FILE'
  49. X/* IsOn... Copyright 1990, 1991 NCEMRSoft.  Use at your own risk!
  50. X    - v1.0 : 1990      : Phil Dietz, NCEMRSoft.
  51. X                       : Original release.    
  52. X    - v2.0 : 05 Feb 91 : Phil Dietz, NCEMRSoft.
  53. X                       : Added 'finger'ing remote machines.
  54. X                       : Names and searches are now case insensitive.
  55. X    - v3.0 : 04 Aug 91 : Mike Gleason, NCEMRSoft.
  56. X                       : Complete rewrite, using unix system calls.
  57. X                       : Remote addresses are recognized automatically.
  58. X                       : IsOn nice's (lowers it's priority) itself.
  59. X                       : Remote commands are exec'd instead of subshelled.
  60. X                       : Uses handy getopt() function.
  61. X                       : Added -f option, in case you don't have finger,
  62. X                       :   our finger flags don't work, or want to try
  63. X                       :   it rwho, etc.
  64. X                       : Added -d debugging option, so you can watch
  65. X                       :   ison's progress.  This is also useful if you
  66. X                       :   want to log to a file.
  67. X                       
  68. X    To compile: "cc -O ison.c -o ison"   */
  69. X
  70. X#define VERSION_STR "Version 3.0 (04 Aug 91)"
  71. X
  72. X#include <sys/types.h>
  73. X#include <sys/time.h>
  74. X#include <utmp.h>
  75. X#include <stdio.h>
  76. X#include <ctype.h>
  77. X
  78. X#define SZ(expr) ((size_t) (expr))
  79. X#define DSLEEP 10       /* seconds to delay between iterations */
  80. X#define DDEBUG 0        /* prints stuff if > 0 */
  81. X#define DMAXITER -1L    /* loop forever until we find the guy */
  82. X#define DCOMMAND NULL   /* command line to do when user is found */
  83. X#define DFINGER "finger -fq"
  84. X
  85. X#ifndef INDEX
  86. X#   ifdef _SYSTYPE_SYSV
  87. X#       define INDEX strchr
  88. X#   else    /* bsd */
  89. X#       define INDEX index
  90. X#   endif
  91. X#endif
  92. X
  93. Xextern size_t fread();
  94. Xextern FILE *fopen(), *popen();
  95. Xextern char *INDEX();
  96. Xint strnicmp(), Nice(), Utmp(), Finger();
  97. X
  98. Xmain(argc, argv)
  99. X    int argc;
  100. X    char **argv;
  101. X{
  102. X    int                 sleep_sec = DSLEEP;
  103. X    int                 debug = DDEBUG;
  104. X    long                maxiter = DMAXITER;
  105. X    int                 notfound, flag;
  106. X    char                *username, hostname[64], *cp;
  107. X    char                *fingercmd = DFINGER;
  108. X    char                *cmd = DCOMMAND;
  109. X    time_t              logontime;
  110. X    extern int          getopt(), optind;   /* getopt() stuff */
  111. X    extern char         *optarg;            /* getopt() stuff */
  112. X
  113. X    if (argc <= 1)
  114. X        usage (argv[0], fingercmd);
  115. X
  116. X    while ((flag = getopt (argc, argv, "dvs:p:i:f:")) != EOF)
  117. X        switch(flag) {
  118. X            case 'd':
  119. X            case 'v':   /* debug mode, verbose mode, same thing */
  120. X                debug++;
  121. X                break;
  122. X            case 's':
  123. X                cmd = optarg;
  124. X                break;
  125. X            case 'p':
  126. X                sleep_sec = atoi (optarg);
  127. X                if (sleep_sec < 0) sleep_sec = DSLEEP;
  128. X                break;
  129. X            case 'i':
  130. X                maxiter = (long) atol (optarg);
  131. X                break;
  132. X            case 'f':
  133. X                fingercmd = optarg;
  134. X                break;
  135. X            default: usage (argv[0], fingercmd);
  136. X        }
  137. X    username = argv[optind];
  138. X    if (username == NULL || strlen(username) == SZ(0))
  139. X        usage (argv[0], fingercmd); /* no user specified! */
  140. X        
  141. X    /* lower our process' priority (nice) */
  142. X    if (Nice (getpid ()))
  143. X        perror ("Nice");
  144. X    
  145. X    /*  Check the username for an @, which would suggest that it is
  146. X        a domain-style address. */
  147. X    if ((cp = INDEX (username, (int)'@')) != NULL) {
  148. X        strcpy (hostname, cp);  /* @machine.domain.xxx */
  149. X        *cp = '\0';             /* shorten address down to just username */
  150. X        notfound = Finger (username, sleep_sec, maxiter, argv[0],
  151. X            hostname, fingercmd, debug);
  152. X        time(&logontime);
  153. X    } else
  154. X        notfound = Utmp (username, sleep_sec, maxiter, argv[0],
  155. X            debug, &logontime);
  156. X
  157. X    /* See if the user was found.  If not, explain why not. */
  158. X    if (notfound != 0) {
  159. X        if (notfound > 0)   /* maxiter encoutered */
  160. X            (void) fprintf (stderr, "## %s is not on.\n", username);
  161. X        else (void) fprintf (stderr,
  162. X            "## %s: cannot go on because of errors.\n", argv[0]);
  163. X    } else {
  164. X        /* When we get here, the user we're looking for was detected. */
  165. X        (void) fprintf (stderr, "** %s%s logged in since %s",
  166. X#ifdef NO_BEEP
  167. X            "",
  168. X#else
  169. X            "\007",     /* Control-G, the ascii BEL character */
  170. X#endif
  171. X            username, ctime(&logontime));
  172. X        if (cmd != NULL) {
  173. X            /* Run a command (script) if the user requested to. */
  174. X            (void) execlp ("/bin/sh", "sh", "-c", cmd, NULL);
  175. X            (void) perror (cmd);
  176. X        }
  177. X    }
  178. X    exit (notfound);
  179. X}   /* main */
  180. X
  181. X
  182. X
  183. X
  184. Xint Utmp(username, sleep_sec, maxiter, progname, debug, tyme)
  185. X    char                *username, *progname;
  186. X    int                 sleep_sec, debug;
  187. X    long                maxiter;
  188. X    time_t              *tyme;
  189. X{
  190. X    struct utmp         info;
  191. X    FILE                *in;
  192. X    register int        not_on = 1, iter = 1;
  193. X    register size_t     unamelen = strlen (username);
  194. X
  195. X    /* Open the utmp file, which is a list of all logged on users. */
  196. X    if ((in = fopen (UTMP_FILE, "r")) == NULL) {
  197. X        (void) perror (UTMP_FILE);
  198. X        return (1);
  199. X    }
  200. X    
  201. X    do {
  202. X        if (debug > 0) {
  203. X            time(tyme);
  204. X            (void) printf("## %s: checking utmp (try #%d) at %s",
  205. X                progname, iter, ctime(tyme));
  206. X        }
  207. X
  208. X        /* Reset the utmp file and re-read it. */
  209. X        (void) rewind (in);
  210. X        
  211. X        /* Cycle through all 'users' logged in. */
  212. X        while (not_on && (fread (&info, SZ(sizeof (info)), SZ(1), in)) == SZ(1)) {
  213. X            not_on = strnicmp(info.ut_name, username, unamelen);
  214. X            if (debug > 1 && *info.ut_name) {
  215. X                info.ut_name[8] = '\0';
  216. X                printf("%s\n", info.ut_name);
  217. X            }
  218. X        }
  219. X        
  220. X        /* Delay a little so we won't hog the CPU */
  221. X        if (not_on) {
  222. X            if (maxiter > 0 && ++iter > maxiter) {
  223. X                not_on = 1; break;
  224. X            }
  225. X            (void) sleep (sleep_sec);
  226. X        }
  227. X    } while (not_on);
  228. X    
  229. X    *tyme = info.ut_time;   /* will hold garbage if user not found! */
  230. X    (void) fclose (in);
  231. X    return (not_on);
  232. X}   /* Utmp */
  233. X
  234. X
  235. X
  236. X
  237. Xint Finger(username, sleep_sec, maxiter, progname, hostname, fingercmd, debug)
  238. X    char *username, *progname, *hostname, *fingercmd;
  239. X    int sleep_sec, debug;
  240. X    long maxiter;
  241. X{
  242. X    FILE                *in;
  243. X    register int        not_on = 1, iter = 1, piperesult;
  244. X    register size_t     unamelen = strlen (username);
  245. X    extern int          errno;
  246. X    char                buf[160], pipename[128];
  247. X    time_t              now;
  248. X    
  249. X    strcpy(pipename, fingercmd);
  250. X    strcat(pipename, " ");
  251. X    if (strnicmp("finger", fingercmd, SZ(6)) != 0)
  252. X        hostname++; /* Skip the @ sign if it's not finger! */
  253. X    strcat(pipename, hostname);
  254. X    
  255. X    do {
  256. X        if (debug > 0) {        
  257. X            time(&now);
  258. X            (void) printf("## %s: %s (try #%d), at %s",
  259. X                progname, pipename, iter, ctime(&now));
  260. X        }
  261. X        
  262. X        if ((in = popen (pipename, "r")) == NULL) {
  263. X            perror (fingercmd);
  264. X            not_on = -errno;
  265. X            break;
  266. X        }
  267. X        
  268. X        /* Cycle through all 'users' logged in. */
  269. X        while (not_on && fgets (buf, (int)sizeof(buf), in) != NULL) {
  270. X            if (debug > 1) printf(buf);
  271. X            not_on = strnicmp(buf, username, unamelen);
  272. X        }
  273. X        
  274. X        piperesult = pclose(in);            /* close pipe */
  275. X        if (piperesult && not_on) {
  276. X            not_on = (piperesult > 0) ? -piperesult : piperesult;
  277. X            break;
  278. X        }
  279. X        
  280. X        /* Delay a little so we won't hog the CPU */
  281. X        if (not_on) {
  282. X            if (maxiter > 0 && ++iter > maxiter) {
  283. X                not_on = 1; break;
  284. X            }
  285. X            (void) sleep (sleep_sec);
  286. X        }
  287. X    } while (not_on);
  288. X    return (not_on);
  289. X}   /* Finger */
  290. X
  291. X
  292. X
  293. Xstrnicmp(a, b, n)
  294. X    char *a, *b;
  295. X    register size_t n;
  296. X{
  297. X    register int i;
  298. X    
  299. X    for ( ; tolower(*a) == tolower(*b) && n-- > 0; a++, b++)
  300. X        if (*a == '\0')
  301. X            return (0); /* equal */
  302. X    return (n <= 0 ? 0 : tolower(*a) - tolower(*b));
  303. X}
  304. X
  305. X
  306. X
  307. X
  308. Xusage(progname, fingercmd)
  309. X    char *progname, *fingercmd;
  310. X{   
  311. X    (void) fprintf (stderr,
  312. X"usage: %s [-p N] [-i N] [-s cmd] [-f cmd] [-d] username &\n\
  313. X\t-p N   : Delay 'N' seconds between iterations (default 10).\n\
  314. X\t-i N   : Give up after 'N' iterations (default is infinity)\n\
  315. X\t-s cmd : Command to execute when user is found (i.e. \"talk username\")\n\
  316. X\t-f cmd : Command to execute for remote addresses (def: \"%s\")\n\
  317. X\t-d     : Debugging mode. More d's, more stuff.\n\n\
  318. X%s by Phil Dietz & Mike Gleason, NCEMRSoft.\n\
  319. XThis is TuitionWare.  Please send a buck to help us through school!\n\
  320. X\tPhil Dietz, Box 306, Yutan, NE  68073, USA... Thanks!\n\n",
  321. X    progname, fingercmd, VERSION_STR);
  322. X    exit (1);
  323. X}   /* usage */
  324. X
  325. X
  326. X
  327. X
  328. X#include <sys/resource.h>
  329. X#define DEFAULT_NICE_INCREMENT 10
  330. X
  331. Xint Nice(pid)
  332. X    pid_t pid;
  333. X{
  334. X    extern int errno;
  335. X    register int priority;
  336. X
  337. X#ifndef NOT_NICE        /* #define it if you don't want to be nice'd */
  338. X    errno = 0;  /* clear it, since priority can be -1! */
  339. X    priority = getpriority(PRIO_PROCESS, pid);
  340. X    if (errno == 0) {
  341. X        priority += DEFAULT_NICE_INCREMENT;
  342. X        if (priority > PRIO_MAX)
  343. X            priority = PRIO_MAX;
  344. X        (void) setpriority(PRIO_PROCESS, pid, priority);
  345. X    }
  346. X#endif
  347. X    return (errno);
  348. X}   /* Nice */
  349. X
  350. X/* eof */
  351. END_OF_FILE
  352. if test 9646 -ne `wc -c <'ison.c'`; then
  353.     echo shar: \"'ison.c'\" unpacked with wrong size!
  354. fi
  355. # end of 'ison.c'
  356. fi
  357. if test -f 'ison.readme' -a "${1}" != "-c" ; then 
  358.   echo shar: Will not clobber existing file \"'ison.readme'\"
  359. else
  360. echo shar: Extracting \"'ison.readme'\" \(764 characters\)
  361. sed "s/^X//" >'ison.readme' <<'END_OF_FILE'
  362. XIsOn's purpose is to let you know when someone logs on.  You could always sit
  363. Xthere at your terminal typing 'finger' or 'who' every 5 minutes, but that's
  364. Xboring and unproductive.  IsOn makes this easy.  If you wanted to know the
  365. Xinstant I logged on, all it would take is a simple:
  366. X
  367. X   ison mgleason@cse.unl.edu &
  368. X
  369. XWhen I do log on, ison would respond:
  370. X
  371. X   ** mgleason logged in since Wed Oct 16 02:19:33 1991
  372. X
  373. XIsOn lowers it's priority automatically, so it takes very little CPU, and
  374. Xspares you the trouble of remembering to use 'nice.'  For remote addresses
  375. X(those in dude@machine.domain format) the 'finger' utility is used, or for
  376. Xa user on the same machine that you are on, IsOn will simply walk the 'utmp'
  377. Xfile.
  378. X
  379. XEnjoy!
  380. X--mike gleason = mgleason@cse.unl.edu
  381. X
  382. END_OF_FILE
  383. if test 764 -ne `wc -c <'ison.readme'`; then
  384.     echo shar: \"'ison.readme'\" unpacked with wrong size!
  385. fi
  386. # end of 'ison.readme'
  387. fi
  388. echo shar: End of shell archive.
  389. exit 0
  390. --
  391. ______________________________________________________________________________
  392. mike gleason                 mgleason@cse.unl.edu             NCEMRSoft, baby!
  393.  
  394. exit 0 # Just in case...
  395. -- 
  396. Kent Landfield                   INTERNET: kent@sparky.IMD.Sterling.COM
  397. Sterling Software, IMD           UUCP:     uunet!sparky!kent
  398. Phone:    (402) 291-8300         FAX:      (402) 291-4362
  399. Please send comp.sources.misc-related mail to kent@uunet.uu.net.
  400.